﻿using System;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Casamiel.API.Application;
using Casamiel.API.Application.Models;
using Casamiel.API.Application.Models.ICModels;
using Casamiel.API.Application.Services;
using Casamiel.Common;
using Casamiel.Domain.Response;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using NLog;

namespace Casamiel.API.Controllers.V1
{
    /// <summary>
    /// 库存
    /// </summary>nt
    [ApiVersion("1.0")]
    [Produces("application/json")]
    [Route("api/v{api-version:apiVersion}/[controller]")]
    [ApiController]
    [RequestFormLimits(ValueCountLimit = int.MaxValue, KeyLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue, MultipartBoundaryLengthLimit = int.MaxValue)]
    public class StockController : Controller
    {
        private readonly IIcApiService _icApiService;
        private readonly string _apitoken;
        private readonly string appkey;
        private readonly string signKey;
        private readonly string apptoken;
        private readonly IStockService _stockService;
        private readonly NLog.ILogger logger = LogManager.GetLogger("StockService");
        /// <summary>
        /// 
        /// </summary>
        /// <param name="icApiService"></param>
        /// <param name="snapshot">snapshot</param>
        ///  <param name="settings">settings</param>
        /// <param name="stockService">stockService</param>
        public StockController(IIcApiService icApiService, IOptionsSnapshot<CasamielSettings> snapshot, IOptionsSnapshot<IcServiceSettings> settings, IStockService stockService)
        {
            if (snapshot == null) {
                throw new ArgumentNullException(nameof(snapshot));
            }

            if (settings == null) {
                throw new ArgumentNullException(nameof(settings));
            }

            _icApiService = icApiService;
            _apitoken = snapshot.Value.ApiToken;
            appkey = settings.Value.appKey;
            signKey = settings.Value.signKey;
            apptoken = settings.Value.token;
            _stockService = stockService;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("[action]")]
        public BaseResult<long> GetUnpushtime()
        {
            var i = _stockService.GetUnpushtime();
            return new BaseResult<long>(i, 0, "");
        }

        /// <summary>
        /// Stockpushplan the specified data and token.
        /// </summary>
        /// <returns>The stockpushplan.</returns>
        /// <param name="data">Data.</param>
        /// <param name="token">Token.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> stockpushplan([FromBody] StockpushPlanReq data, [FromHeader(Name = "u-token")] string token)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            var zmodel = await _icApiService.Stockpushplan(data).ConfigureAwait(false);
            return new JsonResult(zmodel);
        }
        /// <summary>
        /// 库存查询
        /// </summary>
        /// <param name="data"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> QueryStock([FromBody] Domain.Request.IC.IcPriceReq data, [FromHeader(Name = "u-token")] string token)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            if (token != _apitoken) {
                Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                return Ok(new { code = 99999, msg = "token无效" });
            }
            if (data.Shopid < 1) {
                return Ok(new { code = 99999, msg = "门店id不对" });
            }
            var zmodel = await _icApiService.ProductstockqueryAsync(data).ConfigureAwait(false);
            return new JsonResult(zmodel);
        }
        private static string GenerateRandomCode(int length)
        {
            var result = new StringBuilder();
            for (var i = 0; i < length; i++) {
                if (i == 0) {
                    // Console.WriteLine(Guid.NewGuid().GetHashCode());
                    var r = new Random(Guid.NewGuid().GetHashCode());
                    result.Append(r.Next(1, 10));
                } else {
                    var r = new Random(Guid.NewGuid().GetHashCode());
                    result.Append(r.Next(0, 10));
                }

            }
            return result.ToString();
        }

        /// <summary>
        /// 测试
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public IActionResult UpdateStockTest()
        {
            logger.Trace($"UpdateStock");
            return Ok(new { code = 0, msg = "处理成功" });
        }
        /// <summary>
        /// 更新库存
        /// 一网推送过来
        /// </summary>
        /// <param name="req"></param>
        /// <returns>The stock.</returns>
        [HttpPost]
        [Route("[action]")]
        public IActionResult UpdateStock([FromForm]  UpdateStockReq req)
        {
            if (req == null) {
                throw new ArgumentNullException(nameof(req));
            }
            //  logger.Trace($"UpdateStock:token:{token},sign:{sign},content:{content}");
            var _sc = new SimpleStringCypher(appkey);
            var _content = _sc.Decrypt(req.content);
            //logger.Trace($"UpdateStock:{_content}");
            string signData = Sign("token" + req.token + "content" + _content, signKey, signKey);
            //System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            if (req.sign != signData) {
                logger.Trace($"UpdateStock:签名错误,token:{req.token},sign:{req.sign},content:{req.content}");
                return Ok(new { code = 12, msg = "签名错误" });
            }
            // return Ok(new { code = 0, msg = "处理成功" });

            var push = JsonConvert.DeserializeObject<StockPush>(_content);

            _stockService.AddQueue(push);

            logger.Trace($"UpdateStock:处理成功");
            //List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>();
            //paramList.Add(new KeyValuePair<String, String>("token", token));
            //paramList.Add(new KeyValuePair<String, String>("sign", signData));
            //paramList.Add(new KeyValuePair<String, String>("content", _content));
            return Ok(new { code = 0, msg = "处理成功" });
        }
        /// <summary>
        /// Stocks the test.
        /// </summary>
        /// <returns>The test.</returns>
        /// <param name="content">Content.</param>
        [HttpPost]
        [Route("[action]")]
        public IActionResult StockTest(string content)
        {

            var _sc = new SimpleStringCypher(appkey);
            var _content = _sc.Encrypt(content);
            //var data = "";
            string signData = Sign("token" + apptoken + "content" + content, signKey, signKey);
            return Ok(new { content = _content, sign = signData });
        }
        /// <summary>
        /// 签名字符串
        /// </summary>
        /// <param name="prestr">需要签名的字符串</param>
        /// <param name="keyPre">密钥：前置密钥</param>
        /// <param name="keyAfter">密钥：后置密钥</param>
        /// <param name="inputCharset">编码格式</param>
        /// <returns>签名结果</returns>
        public static string Sign(string prestr, string keyPre, string keyAfter, string inputCharset = "utf-8")
        {
            StringBuilder sb = new StringBuilder(32);

            prestr = keyPre + prestr + keyAfter;

            using (MD5 md5 = new MD5CryptoServiceProvider()) {
                byte[] t = md5.ComputeHash(Encoding.GetEncoding(inputCharset).GetBytes(prestr));
                for (int i = 0; i < t.Length; i++) {
                    sb.Append(t[i].ToString("x").PadLeft(2, '0'));
                }
                return sb.ToString();
            }

        }
    }

}